package prototype.controller;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.log4j.Logger;
import prototype.exception.UnauthorizedException;
import prototype.listener.ServletContextListenerImpl;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;

/**
 *
 */
public abstract class AbstractController extends HttpServlet {
	public static final String REQUEST_DATA = "data";

	protected Gson gson;
	private EntityManagerFactory entityManagerFactory;

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		gson = ServletContextListenerImpl.getGson();
		entityManagerFactory = ServletContextListenerImpl.getEntityManagerFactory();
	}

	@Override
	protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
		long time = System.currentTimeMillis();
		Writer writer = null;
		EntityManager entityManager = null;
		try {
			request.setCharacterEncoding("UTF-8");
			response.setCharacterEncoding("UTF-8");
			writer = response.getWriter();
			entityManager = entityManagerFactory.createEntityManager();
			final HttpSession session = request.getSession(true);

			final JsonElement requestData = gson.fromJson(request.getParameter(REQUEST_DATA), JsonElement.class);
			final JsonObject responseData = execute(entityManager, session, requestData);
			response.setContentType("application/json");
			if (responseData != null)
				writer.write(responseData.toString());
		} catch (UnauthorizedException e) {
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			response.setContentType("text/plain");
			writer.write(e.getMessage());
			getLog().error("Error doPost", e);
		} catch (NullPointerException e) {
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			response.setContentType("text/plain");
			e.printStackTrace(new PrintWriter(writer));
			getLog().error("Error doPost", e);
		} catch (Exception e) {
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			response.setContentType("text/plain");
			writer.write(e.getMessage());
			getLog().error("Error doPost", e);
		} finally {
			if (entityManager != null && entityManager.isOpen()) {
				final EntityTransaction transaction = entityManager.getTransaction();
				if (transaction != null && transaction.isActive()) {
					transaction.rollback();
				}
				entityManager.close();
			}
			time = System.currentTimeMillis() - time;
			getLog().debug(time + " ms");
		}
	}

	protected final Logger getLog() {
		return Logger.getLogger(this.getClass());
	}


//	public static UserContext getUserContext(final HttpSession session) throws UnauthorizedException {
//		if (session != null) {
//			final UserContext userContext = (UserContext) session.getAttribute(SessionConst.SESSION_USER);
//			if (userContext != null)
//				return userContext;
//		}
//		throw UnauthorizedException.getInstance();
//	}

//    public static void commit(final EntityManager entityManager) throws SQLException {
//        if (entityManager != null && entityManager.isOpen()) {
//            final EntityTransaction transaction = entityManager.getTransaction();
//            if (transaction != null && transaction.isActive()) {
//                transaction.commit();
//            }
//        }
//    }

	protected abstract JsonObject execute(final EntityManager entityManager, final HttpSession session, final JsonElement requestData) throws Exception;
}
